package demos.consumer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Semaphore;

public class MyBlockingQueue2<T> {
    public static void main(String[] args) {
        MyBlockingQueue2<Integer> queue2 = new MyBlockingQueue2<>(3);
        new Thread(() -> {
            for (int i = 0; i < 10; ++i) {
                queue2.put(i);
            }
        }).start();
        new Thread(() -> {
            for (int i = 0; i < 10; ++i) {
                queue2.take();
            }
        }).start();
    }

    private final Semaphore empty;
    private final Semaphore full;
    private final Semaphore mutex = new Semaphore(1);
    private Queue<T> queue = new LinkedList<>();

    public MyBlockingQueue2(int capacity) {
        this.full = new Semaphore(0);
        this.empty = new Semaphore(capacity);
    }

    public void put(T data) {
        try {
            empty.acquire();
            mutex.acquire();
            queue.add(data);
            System.out.println("put in, size = " + queue.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mutex.release();
            full.release();

        }
    }

    public T take() {
        T t = null;
        try {
            full.acquire();
            mutex.acquire();
            t = queue.remove();
            System.out.println("    take out, size = " + queue.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            mutex.release();
            empty.release();

        }
        return t;
    }
}
